home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 February: Tool Chest / Apple Developer CD Series Tool Chest February 1996 (Apple Computer)(1996).iso / Sample Code / System 7.0 Samples / AEObject-Edition1.0.2 Sample / Files.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-18  |  31.6 KB  |  789 lines  |  [TEXT/MPS ]

  1. /*------------------------------------------------------------------------------
  2. *
  3. *  Apple Developer Technical Support
  4. *
  5. *  I/O handling routines
  6. *
  7. *  Program:    AEObject-Edition Sample
  8. *  File:       Files.c -   C Source
  9. *
  10. *  by:         C.K. Haun <TR>
  11. *
  12. *  Copyright © 1990-1992 Apple Computer, Inc.
  13. *  All rights reserved.
  14. *
  15. *------------------------------------------------------------------------------
  16. * This file handles saving and loadingg the documents created by this sample.
  17. * All the standard data load/save is taken care of in this file, while the 
  18. * Edition Manager specific routines for handling sections are in their own files  
  19. * (Publish.c or Subscribe.c) and are called from here.
  20. *----------------------------------------------------------------------------*/
  21.  
  22. /* File handling here */
  23. #define __FILES__
  24.  
  25. #pragma segment Files
  26.  
  27. #include "Sampdefines.h"
  28.  
  29. static OSErr KillOldPrefs(void);
  30.  
  31. /*  SaveMe saves the passes window data, and all the associated sections.
  32. *       It does NOT perform a 'safe' save, it kills the old data and recreates it.
  33. *       Future versions of this sample will do a 'safe' save.  Yeah, right, I wouldn't
  34. *        beleive me on THAT one.
  35. */
  36. /* windowCHandle is locked on entry to this  */
  37. void SaveMe(windowCHandle theWind, WindowPtr theWindPtr)
  38. {
  39.     Boolean myWasChanged;    /* for Alias Manager calls */
  40.     register qq;            /* counter */
  41.     StandardFileReply saveReply;    /* new System 7 standard file record */
  42.     short saveRefNum;
  43.     FSSpec saveFileSpec;
  44.     OSErr myErr;
  45.     Str255 wName;
  46.     Str63 savePrompt;
  47.     Handle nameStr;
  48.     long toWrite;    /* generic long */
  49.     
  50.     /* we need the window title for a prompt and also to change the name */
  51.     /* in the Window menu */
  52.     GetWTitle(theWindPtr, wName);
  53.     /* if the filealias handle is 0 size, then this file has not been saved yet, so we  */
  54.     /* need to call Standard File.  I'm using the new StandardGetFile call, this */
  55.     /* call is better in (at least) two ways.  First, you no longer pass a Point as */
  56.     /* a parameter, instead, the dialog is centered on the main screen for you.  Secondly, */
  57.     /* StandardGetFile returns a FSSpec record in the reply record.  This means that you */
  58.     /* can use the new FSp type calls, as well as using the FSSpec to generate an Alias */
  59.     /* easily. */
  60.     /* By the Way... if this is a 'Save As...' I have nulled out this handle so it */
  61.     /* looks like it's never been saved, look in Menus.c */    
  62.     if (GetHandleSize((Handle)(*theWind)->fileAliasHandle) == 0) {
  63.         /* get our prompt string */
  64.         GetIndString(savePrompt, kGeneralStrings, kSavePromptString);
  65.         /* display the new dialog */
  66.         StandardPutFile(savePrompt, wName, &saveReply);
  67.         if (!saveReply.sfGood)    /* did the user cancel? */
  68.             return;
  69.         /* get the returned file spec */    
  70.         saveFileSpec = saveReply.sfFile;
  71.         /* if they are replacing, destroy the old file now (aaaggggg) */
  72.         if (saveReply.sfReplacing)
  73.             FSpDelete(&saveFileSpec);
  74.         /* change the name of the window to this filename */
  75.         SetWTitle(theWindPtr, saveFileSpec.name);
  76.         AddToWindowMenu(theWindPtr,wName); /* remove the old name and replace it with this */
  77.     } else {
  78.         /* Resolve the old alias that was kept with the window  */
  79.         /* in this case I don't care if the alias needed to be updated or not, this ain't */
  80.         /* a real time critical routine */
  81.         myErr = ResolveAlias(nil, ((*theWind)->fileAliasHandle), &saveFileSpec, &myWasChanged);
  82.         if (myErr) {
  83.             ShowMe("\pResolving Alias ", myErr, __LINE__);
  84.             return;
  85.         }
  86.         /* kill current file, ignoring errors */
  87.         FSpDelete(&saveFileSpec);
  88.     }
  89.     SpinCursor();
  90.     /* create the new file */
  91.     myErr = FSpCreate(&saveFileSpec, kMySignature, kMyDocumentFileType, 1);
  92.     if (myErr) {
  93.         ShowMe("\pCreating file ", myErr, __LINE__);
  94.         SetMyCursor(actsToIDs[(*theWind)->currentAction]);
  95.         return;
  96.     }
  97.     
  98.     /* replace the nil handle with the alias record please, in our window data struct */
  99.     DisposeHandle((Handle)(*theWind)->fileAliasHandle);
  100.     if (myErr = NewAlias(nil, &saveFileSpec, &((*theWind)->fileAliasHandle))) {
  101.         ShowMe("\pDuring New Alias ", myErr, __LINE__);
  102.         SetMyCursor(actsToIDs[(*theWind)->currentAction]);
  103.         return;
  104.     }
  105.     /* First save the drawing commands that make up this window */
  106.     
  107.     myErr = FSpOpenDF(&saveFileSpec, fsRdWrPerm, &saveRefNum);
  108.     if (myErr) {
  109.         ShowMe("\pOpening file ", myErr, __LINE__);
  110.         SetMyCursor(actsToIDs[(*theWind)->currentAction]);
  111.         return;
  112.     }
  113.     /* save off lines, rects, ovals.  If there is a selection currently, it's lost */
  114.     /* shapes */
  115.     toWrite = sizeof(short);
  116.     SpinCursor();
  117.     myErr = FSWrite(saveRefNum, &toWrite, (Ptr)&(*theWind)->numShapes);
  118.     if (myErr) {
  119.         ShowMe("\pWriting file ", myErr, __LINE__);
  120.     }
  121.     if ((*theWind)->numShapes) {
  122.         ShapesHandle theShape = (*theWind)->theShapes;
  123.         do {
  124.             toWrite = sizeof(Shapes);
  125.             HLock((Handle)theShape);
  126.             myErr = FSWrite(saveRefNum, &toWrite, (Ptr)*theShape);
  127.             HUnlock((Handle)theShape);
  128.             if (myErr) {
  129.                 ShowMe("\pWriting shapes ", myErr, __LINE__);
  130.                 break;
  131.             }
  132.             theShape = (*theShape)->nextShape;
  133.         }
  134.                 while (theShape);
  135.     }
  136.     
  137.     /* and pictures, I'm putting them in the data fork just because, OK? */
  138.     /* Actually, I'm doing it to prevent any conflict with resource for  */
  139.     /* subscribers cached pictures.  I could check for unique IDs and all that, but sometimes */
  140.     /* simplicity works well.... */
  141.       if(!myErr){  
  142.     toWrite = sizeof(short);
  143.     SpinCursor();
  144.     myErr = FSWrite(saveRefNum, &toWrite, (Ptr)&(*theWind)->numPicts);
  145.     if(!myErr){
  146.     if ((*theWind)->numPicts != 0) {
  147.         Handle * thePict;
  148.         Handle *thePictRect;
  149.         /* get my picture handles and my picture placement rectangles */
  150.         HLock((Handle)(*theWind)->pictHandle);
  151.         HLock((Handle)(*theWind)->pictRects);
  152.         thePict = (Handle *)*(*theWind)->pictHandle;
  153.         thePictRect = (Handle *)*(*theWind)->pictRects;
  154.         for (qq = 0; qq < (*theWind)->numPicts; qq++) {
  155.             short writeSize;
  156.             toWrite = sizeof(short);
  157.             /* write everything about the picture out */
  158.             writeSize = GetHandleSize((Handle)*thePict);
  159.             myErr = FSWrite(saveRefNum, &toWrite, (Ptr)&writeSize);
  160.             toWrite = writeSize;
  161.             HLock((Handle)*thePict);
  162.             if(!myErr) myErr = FSWrite(saveRefNum, &toWrite, (Ptr)(*(*thePict)));
  163.             HUnlock((Handle)*thePict);
  164.             /* and the rect */
  165.             toWrite = sizeof(Rect);
  166.             HLock((Handle)*thePictRect);
  167.             if(!myErr) myErr = FSWrite(saveRefNum, &toWrite, (Ptr)(*(*thePictRect)));
  168.             HUnlock((Handle)*thePictRect);
  169.             thePictRect += 1;
  170.             thePict += 1;
  171.             SpinCursor();
  172.         }
  173.         HUnlock((Handle)(*theWind)->pictHandle);
  174.         HUnlock((Handle)(*theWind)->pictRects);
  175.     }
  176.     }
  177.     }
  178.     toWrite = sizeof(short);
  179.     /* if there's any text in a TE record, write that out also */
  180.     if(!myErr){
  181.     if ((*theWind)->boxHandle != nil) {
  182.         CharsHandle theText;
  183.         short textLen;
  184.         /* save the text and the rectangle */
  185.         theText = TEGetText((*theWind)->boxHandle);
  186.         HLock((Handle)theText);
  187.         textLen = GetHandleSize((Handle)theText);
  188.         /* have to write it out the length of the text now */
  189.         toWrite = sizeof(short);
  190.         SpinCursor();
  191.         myErr = FSWrite(saveRefNum, &toWrite, (Ptr)&textLen);
  192.         /* and the text itself */
  193.         toWrite = textLen;
  194.         if(!myErr) myErr = FSWrite(saveRefNum, &toWrite, (Ptr)*theText);
  195.         /* and save out the rectangle */
  196.         toWrite = sizeof(Rect);
  197.         if(!myErr) myErr = FSWrite(saveRefNum, &toWrite, (Ptr)&(*theWind)->textBox);
  198.     } else {
  199.         short nothing = 0;
  200.         myErr = FSWrite(saveRefNum, &toWrite, (Ptr)¬hing);       /* a pointer to nothing.  Leads to the 'No Exit' sign in Sartè */
  201.     }
  202.     }
  203.     if(myErr)
  204.         ShowMe("\p Error writing data fork",myErr,__LINE__);
  205.     if(saveRefNum)FSClose(saveRefNum);
  206.     /* this takes care of the data fork of the file.  Now we need to save 
  207.     *   publisher and subcriber data in the resource fork */
  208.     HCreateResFile(saveFileSpec.vRefNum, saveFileSpec.parID, saveFileSpec.name);
  209.     if (myErr = ResError()) {
  210.         ShowMe("\pCreating Rez fork", myErr, __LINE__);
  211.         SetMyCursor(actsToIDs[(*theWind)->currentAction]);
  212.         return;
  213.     }
  214.     saveRefNum = HOpenResFile(saveFileSpec.vRefNum, saveFileSpec.parID, saveFileSpec.name, fsRdWrPerm);
  215.     if (myErr = ResError()) {
  216.         ShowMe("\pHOpening resource fork ", myErr, __LINE__);
  217.         SetMyCursor(actsToIDs[(*theWind)->currentAction]);
  218.         return;
  219.     }
  220.     /* add our 'name' string to this file (see 'The Finder Interface' chapter of IM VI) */
  221.     nameStr = GetResource('STR ', kMyAppNameString);
  222.     DetachResource(nameStr);
  223.     UseResFile(saveRefNum);
  224.     AddResource(nameStr, 'STR ', -16396, ""); /* no constant for this number, should be */
  225.     /* HandleSectionSave saves off the 'sect' and 'alis' resources for all our */
  226.     /* publishers and subscribers */
  227.     HandleSectionSave(theWind, true, false, &saveFileSpec);
  228.     CloseResFile(saveRefNum);
  229.     FlushVol("", saveFileSpec.vRefNum);
  230.     (*theWind)->windowDirty = false;
  231.     SetMyCursor(actsToIDs[(*theWind)->currentAction]);
  232. }
  233.  
  234. /* end SaveMe */
  235.  
  236. /* OpenFile reads in our drawing commands, and all the publisher and */
  237. /* subscriber data, and registers all our sections */
  238. WindowPtr OpenFile(FSSpec *inSpec)
  239. {
  240.     long numSections;
  241.     long counter = 0;
  242.     OSErr myErr;
  243.     WindowPtr newWindow;
  244.     windowCHandle newWinControl;
  245.     Handle textFromFile;
  246.     FSSpec readFileSpec;
  247.     short readRefNum;
  248.     StandardFileReply openReply;
  249.     SFTypeList myList =  {
  250.         kMyDocumentFileType
  251.     };
  252.     
  253.     if (inSpec) {    /* if it was called by an ODOC AppleEvent then our AppleEvent handler */
  254.         /* will pass the FSSpec that the AE contained */
  255.         readFileSpec = openReply.sfFile = *inSpec;
  256.     } else {
  257.     /* if the spec is nil, that means it's a menu selection, so we use StandardFile */
  258.         StandardGetFile(NULL, 1, myList, &openReply);
  259.         if (!openReply.sfGood)
  260.             return(nil);                                    /* scat if they canceled */
  261.         readFileSpec = openReply.sfFile;
  262.     }
  263.     if ((openReply.sfType != kMyDocumentFileType) && (inSpec == nil)) {
  264.         ShowMe("\pfilter not working", 0, __LINE__);
  265.         return(nil);
  266.     }
  267.     if(CheckExisting(&readFileSpec)){
  268.         /* if it already eisists, bring it up */
  269.         WindowToFront(nil,readFileSpec.name);
  270.         return(FrontWindow());
  271.         }
  272.         SpinCursor();
  273.     newWindow = AddNewWindow(false);                        /* ask for a new window */
  274.     if (newWindow == nil) {
  275.         InitCursor();
  276.         return(nil);
  277.     }                                                       /* bail if it failed */
  278.     newWinControl = (windowCHandle)GetWRefCon(newWindow);
  279.     HLock((Handle)newWinControl);
  280.     /* window opened, set title to file name, and create an alias to store in the */
  281.     /* struct. */
  282.     SetWTitle(newWindow, readFileSpec.name);
  283.     DisposeHandle((Handle)(*newWinControl)->fileAliasHandle);        /* kill the null handle */
  284.     if (myErr = NewAlias(nil, &readFileSpec, &((*newWinControl)->fileAliasHandle))) {
  285.         ShowMe("\pDuring New Alias ", myErr, __LINE__);
  286.         return(nil);
  287.     }
  288.     /* now open the data fork of the file and read in our drawing commands */
  289.     if (myErr = FSpOpenDF(&openReply.sfFile, fsRdPerm, &readRefNum)) {
  290.         ShowMe("\pOpening file ", myErr, __LINE__);
  291.         return(nil);
  292.     }
  293.     SpinCursor();
  294.     ReadDocData(newWinControl, readRefNum);
  295.     SpinCursor();
  296.     readRefNum = HOpenResFile(readFileSpec.vRefNum, readFileSpec.parID, readFileSpec.name, fsRdWrPerm);
  297.     UseResFile(readRefNum);
  298.     /* now load in the sections and aliases */
  299.     /* Load each section, and store it in the appropriate area (pub or sub) */
  300.     /* Then register the sections.  */
  301.     /* ••• NOTE: As soon as you register a section, the Edition Manager may generate an */
  302.     /* event for that section.  All the subscribers may get a Section Read event, for */
  303.     /* example, and some of the publishers will probably get a section write.  */
  304.     /*  So, don't assume anything.  Don't write sections or read sections yourself, wait for */
  305.     /* the Edition Manager to generate the right events, this will insure that you are always */
  306.     /* current and NOT fighting with the EM */
  307.     /* how many sections are there? */
  308.     numSections = Count1Resources(rSectionType);
  309.     /* loop through them all */
  310.     if (numSections) {
  311.         for (counter = 0; counter < numSections; counter++) {
  312.             SectionHandle inSection;
  313.             AliasHandle inAlias;
  314.             Handle auxDataIn;
  315.             short inID;
  316.             ResType tempRT;
  317.             Str255 tempRName;
  318.             Boolean aliasUpdated;
  319.             SpinCursor();
  320.             inSection = (SectionHandle)Get1IndResource(rSectionType, counter + 1);
  321.             /* this GetResInfo call is here to give us the ResID of the section.  Since the alias */
  322.             /* for this section was stored with the same ID, we can get it easily. */
  323.             GetResInfo((Handle)inSection, &inID, &tempRT, &tempRName);
  324.             inAlias = (AliasHandle)Get1Resource(rAliasType, inID);
  325.             myErr = ResError();
  326.             if ((myErr != 0) || (inAlias == nil))
  327.                 ShowMe("\palias error", myErr, __LINE__);
  328.             DetachResource((Handle)inSection);
  329.             DetachResource((Handle)inAlias);
  330.             /* depending on our type depends on what else we bring in */
  331.             /* text data or picture stuff */
  332.             switch ((*inSection)->refCon & 0xf) {
  333.                 case kPictType:
  334.                     auxDataIn = Get1Resource('RECT', inID);
  335.                     DetachResource(auxDataIn);
  336.                     break;
  337.                 case kTextType:
  338.                     /* I do need */
  339.                     /* to get my textSection record back so I have my start-end offsets */
  340.                     auxDataIn = Get1Resource(rMyTextRecordType, inID);
  341.                     DetachResource(auxDataIn);
  342.                     break;
  343.                     
  344.             }
  345.             /* Put the alias in the section, since the old handle stored there means nothing now */
  346.             
  347.             (*inSection)->alias = inAlias;
  348.             /* now we have to determine if this was a pub or sub, since we have to load the */
  349.             /* publish rectangle resource if it was a publisher */
  350.             /* Now tell the Edition Manager that this section is back on line and ready to */
  351.             /* receive events */
  352.             if (myErr = RegisterSection(&readFileSpec, inSection, &aliasUpdated)) {
  353.                 ShowMe("\pRegistering Section ", myErr, __LINE__);
  354.                 /*    return; */
  355.                 inSection = nil;
  356.             }
  357.             if (inSection) {
  358.                 
  359.                 if ((*inSection)->kind == stPublisher) {
  360.                     
  361.                     /* get the rectangle */
  362.                     switch ((*inSection)->refCon & 0xf) {
  363.                         case kPictType:
  364.                             HLock(auxDataIn);
  365.                             StorePublisher(newWinControl, inSection, (Rect *)*auxDataIn, nil, 'PICT');  /* in Publish.c */
  366.                             DisposeHandle(auxDataIn);
  367.                             /* mark all incoming sections as having been saved once, so we don't */
  368.                             /* delete them accidentalllly when this window closes */
  369.                             (*inSection)->refCon |= kSavedOnce;
  370.                             
  371.                             break;
  372.                         case kTextType:
  373.                             /* need to get the text contained in this thing */
  374.                             textFromFile = Get1Resource(rMyTextBlock, inID);
  375.                             DetachResource(textFromFile);
  376.                             (*(mySectionDataHandle)auxDataIn)->additionalData = textFromFile;
  377.                             /* associate the section with the text section */
  378.                             (*(mySectionDataHandle)auxDataIn)->theSection = inSection;
  379.                             /* and store it away */
  380.                             
  381.                             StorePublisher(newWinControl, inSection, nil, (mySectionDataHandle)auxDataIn, 'TEXT');
  382.                             /* mark all incoming sections as having been saved once, so we don't */
  383.                             /* delete them accidentalllly when this window closes */
  384.                             (*inSection)->refCon |= kSavedOnce;
  385.                             break;
  386.                             
  387.                     }
  388.                 } else {
  389.                     Handle picIn;
  390.                     switch ((*inSection)->refCon & 0xf) {
  391.                         case kPictType:
  392.                             picIn = (Handle)GetPicture(inID);
  393.                             DetachResource((Handle)picIn);
  394.                             if (ResError())
  395.                                 ShowMe("\ppicture get", 0, __LINE__);
  396.                             /* need to get the picture here */
  397.                             StoreSubscriber(newWinControl, inSection, auxDataIn, picIn);        /* in Subscribe.c */
  398.                             break;
  399.                         case kTextType:
  400.                             /* need to get the text contained in this thing */
  401.                             textFromFile = Get1Resource(rMyTextBlock, inID);
  402.                             DetachResource(textFromFile);
  403.                             (*(mySectionDataHandle)auxDataIn)->additionalData = textFromFile;
  404.                             /* associate the section with the text section */
  405.                             (*(mySectionDataHandle)auxDataIn)->theSection = inSection;
  406.                             (*(mySectionDataHandle)auxDataIn)->nextSection = nil;
  407.                             /* and store it away */
  408.                             /* I'll be using the auxDataIn field for the mySectionDataHandle */
  409.                             StoreSubscriber(newWinControl, inSection, auxDataIn, nil);      /* in Subscribe.c */
  410.                             
  411.                             break;
  412.                     }
  413.                 }
  414.             }
  415.         }
  416.     }
  417.     CloseResFile(readRefNum);
  418.     (*newWinControl)->windowDirty = false;                  /* can't be dirty if I just opend it */
  419.     HUnlock((Handle)newWinControl);
  420.     ShowWindow(newWindow);
  421.     AddToWindowMenu(newWindow, nil);
  422.     ChangePlane(newWindow);
  423.     InitCursor();
  424.     return(newWindow);
  425. }
  426.  
  427. /* Reads the actual document data out of the file.  This is not in the OpenFile function */
  428. /* for secret reasons that will become apparent in a future release of this sample..... */
  429. /* the window control structure in this window ptr is locked on entry */
  430. /* I'm passing the window instaed of the window control handle because I may */
  431. /* have to create a text edit record */
  432. void ReadDocData(windowCHandle newWinControl, short readRefNum)
  433. {
  434.     long toRead;
  435.     register qq;
  436.     short aShort;
  437.     OSErr myErr;
  438.     short shapeCounter;
  439.     GetEOF(readRefNum, &toRead);
  440.     if (toRead) {                                           /* Make sure that there is some data to read */
  441.         /* lines */
  442.         toRead = sizeof(short);
  443.         FSRead(readRefNum, &toRead, (Ptr)&shapeCounter);
  444.         if (shapeCounter) {
  445.             ShapesHandle tempSH;
  446.             
  447.             for (qq = 0; qq < shapeCounter; qq++) {
  448.                 tempSH = NewShape(newWinControl);           /* number of shapes is getting incremented in this call */
  449.                 HLock((Handle)tempSH);
  450.                 toRead = sizeof(Shapes);
  451.                 myErr = FSRead(readRefNum, &toRead, (Ptr)*tempSH);
  452.                 if (myErr)
  453.                     ShowMe("\pReading shape", myErr, __LINE__);
  454.                 /* re-nul the nextShape field */
  455.                 (*tempSH)->nextShape = nil;
  456.                 HUnlock((Handle)tempSH);
  457.             }
  458.         }
  459.         toRead = sizeof(short);
  460.         FSRead(readRefNum, &toRead, (Ptr)&(*newWinControl)->numPicts);
  461.         if ((*newWinControl)->numPicts != 0) {
  462.             Handle * tempPictHand;
  463.             Handle *tempPictRects;
  464.             HUnlock((*newWinControl)->pictHandle);
  465.             HUnlock((*newWinControl)->pictRects);
  466.             MySetHandleSize((*newWinControl)->pictHandle, (sizeof(Handle) * ((*newWinControl)->numPicts)));
  467.             MySetHandleSize((*newWinControl)->pictRects, (sizeof(Handle) * ((*newWinControl)->numPicts)));
  468.             HLock((*newWinControl)->pictHandle);
  469.             HLock((*newWinControl)->pictRects);
  470.             tempPictRects = (Handle *)*((*newWinControl)->pictRects);
  471.             tempPictHand = (Handle *)*((*newWinControl)->pictHandle);
  472.             /* read in picts please */
  473.             for (qq = 0; qq < (*newWinControl)->numPicts; qq++) {
  474.                 short sizeIn;
  475.                 /* read size of pict, pict, and pict rect for each */
  476.                 toRead = sizeof(short);
  477.                 FSRead(readRefNum, &toRead, (Ptr)&sizeIn);
  478.                 *tempPictHand = NewHandle(sizeIn);
  479.                 HLock(*tempPictHand);
  480.                 toRead = sizeIn;
  481.                 FSRead(readRefNum, &toRead, (Ptr)(*(*tempPictHand)));
  482.                 HUnlock(*tempPictHand);
  483.                 *tempPictRects = NewHandle(sizeof(Rect));
  484.                 
  485.                 HLock(*tempPictRects);
  486.                 toRead = sizeof(Rect);
  487.                 FSRead(readRefNum, &toRead, (Ptr)(*(*tempPictRects)));
  488.                 HUnlock(*tempPictRects);
  489.                 tempPictRects += 1;
  490.                 tempPictHand += 1;
  491.             }
  492.             HUnlock((*newWinControl)->pictHandle);
  493.             HUnlock((*newWinControl)->pictRects);
  494.             
  495.         }
  496.         /* get any text */
  497.         toRead = sizeof(short);
  498.         FSRead(readRefNum, &toRead, (Ptr)&aShort);
  499.         if (aShort) {                                       /* if this has value (numerically, not ethically) then we need to make a TERecord */
  500.             CharsHandle theText;
  501.             Rect innerRect;
  502.             theText = (CharsHandle)NewHandle(aShort);
  503.             HLock((Handle)theText);
  504.             toRead = aShort;
  505.             FSRead(readRefNum, &toRead, (Ptr)*theText);
  506.             /* read in the rect */
  507.             toRead = sizeof(Rect);
  508.             FSRead(readRefNum, &toRead, (Ptr)&(*newWinControl)->textBox);
  509.             /* and create the TEControl */
  510.             innerRect = (*newWinControl)->textBox;
  511.             InsetRect(&innerRect, 3, 3);
  512.             (*newWinControl)->boxHandle = TENew(&innerRect, &(*newWinControl)->textBox);
  513.             TESetText((Ptr)*theText, aShort, (*newWinControl)->boxHandle);
  514.             DisposeHandle((Handle)theText);
  515.         }
  516.     }
  517.     FSClose(readRefNum);
  518. }
  519.  
  520. /* LoadPrefs gets my preferences record out of the prefs file */
  521. void LoadPrefs(void)
  522. {
  523.     Handle prefs;
  524.     short prefFileID = OpenPrefsFile();
  525.     if (prefFileID) {
  526.         UseResFile(prefFileID);
  527.         /* load my private prefs resource */
  528.         prefs = Get1Resource(kMyPrefsResType, 128);
  529.         
  530.         if (prefs) {
  531.         /* it exsists */
  532.         
  533.             HLock(prefs);
  534.             BlockMove((Ptr)*prefs, (Ptr)&gPreferences, sizeof(prefStruct));
  535.               /* first check our version please */
  536.             if(gPreferences.version != kCurrentPrefsVersion){
  537.             ReleaseResource(prefs);
  538.             CloseResFile(prefFileID);            
  539.             if(noErr == KillOldPrefs())
  540.                 LoadPrefs();    /* a little recursion in the morning */
  541.             else
  542.                 return;
  543.             }
  544.             /* parse through and see if we need to xfer object definitions */
  545.             if(gPreferences.saveWindDef){
  546.             HLock((Handle)gWindObjSpecHandle);
  547.             BlockMove((Ptr)&gPreferences.savedWOD,(Ptr)*gWindObjSpecHandle,sizeof(WindowObjectDef));
  548.             HUnlock((Handle)gWindObjSpecHandle);
  549.             }
  550.             if(gPreferences.saveTextDef){
  551.             HLock((Handle)gTextObjSpecHandle);
  552.             BlockMove((Ptr)&gPreferences.savedTOD,(Ptr)*gTextObjSpecHandle,sizeof(TextObjectDef));
  553.             HUnlock((Handle)gTextObjSpecHandle);
  554.             }
  555.             if(gPreferences.saveShapeDef){
  556.             HLock((Handle)gShapeObjSpecHandle);
  557.             BlockMove((Ptr)&gPreferences.savedSOD,(Ptr)*gShapeObjSpecHandle,sizeof(ShapeObjectDef));
  558.             HUnlock((Handle)gShapeObjSpecHandle);
  559.             }
  560.             if(gPreferences.saveInteract){
  561.             gLocalInteraction = gPreferences.localInteraction;
  562.             gAESendInteraction= gPreferences.sendInteraction;
  563.             gAESwitchLayer= gPreferences.layerSwitch;
  564.             }
  565.             if(gPreferences.saveTarget)gAddressMode=gPreferences.targetMode;
  566.             if(gPreferences.saveReply)gReplyMode = gPreferences.replyMode;
  567.  
  568.             HUnlock(prefs);
  569.             ReleaseResource(prefs);
  570.         } else {
  571.         /* some default prefs if the resource is missing */
  572.         gPreferences.bringAEUp=true;
  573.          gPreferences.verboseAE=true;
  574.  
  575.         }
  576.         CloseResFile(prefFileID);
  577.     }
  578. }
  579.  
  580. /* SavePrefs saves my preferences, and creates the prefs resource if none exisiststsists */
  581. void SavePrefs(void)
  582. {
  583.     Handle prefs;
  584.     short prefFileID;
  585.     /* if no change, don't bother */
  586.     if(!gPreferences.prefsChanged)return;
  587.     prefFileID = OpenPrefsFile();
  588.     /* did the file open ???  */
  589.     if (prefFileID) {
  590.         /* yeah, get our resource */
  591.         prefs = Get1Resource(kMyPrefsResType, 128);
  592.         if (prefs) {
  593.         /* it exixsts.  */
  594.             HLock(prefs);
  595.            gPreferences.version = kCurrentPrefsVersion;
  596.            gPreferences.localInteraction=gLocalInteraction;
  597.              gPreferences.sendInteraction=gAESendInteraction;
  598.              gPreferences.layerSwitch=gAESwitchLayer;
  599.             
  600.             gPreferences.targetMode=gAddressMode;
  601.               gPreferences.replyMode=gReplyMode;
  602.  
  603.             /* move our object data into this thing here  */
  604.             HLock((Handle)gWindObjSpecHandle);
  605.             BlockMove((Ptr)*gWindObjSpecHandle,(Ptr)&gPreferences.savedWOD,sizeof(WindowObjectDef));
  606.             HLock((Handle)gTextObjSpecHandle);
  607.             BlockMove((Ptr)*gTextObjSpecHandle,(Ptr)&gPreferences.savedTOD,sizeof(TextObjectDef));
  608.             HLock((Handle)gShapeObjSpecHandle);
  609.             BlockMove((Ptr)*gShapeObjSpecHandle,(Ptr)&gPreferences.savedSOD,sizeof(ShapeObjectDef));
  610.             BlockMove((Ptr)&gPreferences, (Ptr)*prefs, sizeof(prefStruct));
  611.             HUnlock(prefs);
  612.             ChangedResource(prefs);
  613.         } else {
  614.         /* could not load the prefs resource, must not be there.  Create a new one */
  615.             prefs = NewHandle(sizeof(prefStruct));
  616.             HLock(prefs);
  617.             HLock((Handle)gWindObjSpecHandle);
  618.             
  619.             BlockMove((Ptr)*gWindObjSpecHandle,(Ptr)&gPreferences.savedWOD,sizeof(WindowObjectDef));
  620.             HLock((Handle)gTextObjSpecHandle);
  621.             BlockMove((Ptr)*gTextObjSpecHandle,(Ptr)&gPreferences.savedTOD,sizeof(TextObjectDef));
  622.             HLock((Handle)gShapeObjSpecHandle);
  623.             BlockMove((Ptr)*gShapeObjSpecHandle,(Ptr)&gPreferences.savedSOD,sizeof(ShapeObjectDef));
  624.            gPreferences.version = kCurrentPrefsVersion;
  625.             BlockMove((Ptr)&gPreferences, (Ptr)*prefs, sizeof(prefStruct));
  626.             AddResource(prefs, kMyPrefsResType, 128, "");
  627.             ChangedResource(prefs);
  628.         }
  629.         UpdateResFile(prefFileID);
  630.         CloseResFile(prefFileID);
  631.     }
  632. }
  633.  
  634. /* OpenPrefsFile opens, or creates and opens, my preferences file and returns   */
  635. /* the file reference number for it */
  636. short OpenPrefsFile(void)
  637. {
  638.     Handle prefsNameStr;
  639.     FSSpec prefsSpec;
  640.     short foundVREF;
  641.     short prefsID;
  642.     OSErr error;
  643.     long foundDIR;
  644.     /* Use FindFolder to get the dir and volume IDs for the preferences folder */
  645.     /* on the current system disko */
  646.     FindFolder(kOnSystemDisk, kPreferencesFolderType, true, &foundVREF, &foundDIR);
  647.     /* get the name of my prefs file (resource, so it can be localized */
  648.     prefsNameStr = GetResource('STR ', kPrefsFileString);
  649.     HLock(prefsNameStr);
  650.     FSMakeFSSpec(foundVREF, foundDIR, (Str255)*prefsNameStr, &prefsSpec);
  651.     prefsID = FSpOpenResFile(&prefsSpec, fsRdWrPerm);
  652.     /* •••• Note: FSpOpenResFile returnd the file system error in ResError!  */
  653.     /* read the Resource Manager chapter of IM VI for more details */
  654.     error = ResError();
  655.     if (prefsID == -1) {
  656.         /* this means the prefs file couldn't be opened (IM VI chapter 13).  find out why */
  657.         prefsID = 0;                                        /* so later testing works better */
  658.         error = ResError();
  659.         if (error == fnfErr) {
  660.             /* create the file, then reopen it */
  661.             FSpCreateResFile(&prefsSpec, kMySignature, kMyPrefsFileType, 0);
  662.             if (ResError())
  663.                 return(nil);                                /* bail */
  664.             prefsID = FSpOpenResFile(&prefsSpec, fsRdWrPerm);
  665.             error = ResError();
  666.             if (error)
  667.                 return(nil);
  668.             
  669.         }
  670.     }
  671.     ReleaseResource(prefsNameStr);
  672.     return(prefsID);
  673. }
  674.  
  675. /* allows you to save the contents of the AEStatus window to disk.  Can be handy */
  676. void SaveAES(windowCHandle theWind, WindowPtr theWindPtr)
  677. {
  678. #pragma unused (theWindPtr)
  679. OSErr myErr;
  680. Str255 savePrompt;
  681. Str63 defaultName;
  682. StandardFileReply saveReply;
  683. FSSpec saveFileSpec;
  684. Handle theText;
  685. long toWrite;
  686. long textSize = 0;
  687. long currentOffset = 0;
  688. char carrageRet = 0x0d;
  689. long oneByte = 1;
  690. short fileRef;
  691. Boolean myWasChanged;
  692.     if (GetHandleSize((Handle)(*theWind)->fileAliasHandle) == 0) {
  693.         
  694.         GetIndString(savePrompt, kGeneralStrings, kAESSavePrompt);
  695.         GetIndString(defaultName,kGeneralStrings,kAESDefaultName);
  696.         StandardPutFile(savePrompt, defaultName, &saveReply);
  697.         if (!saveReply.sfGood)
  698.             return;
  699.         saveFileSpec = saveReply.sfFile;
  700.         if (saveReply.sfReplacing)
  701.             FSpDelete(&saveFileSpec);
  702.  
  703.  
  704.  
  705.     } else {
  706.         /* Resolve the old alias that was kept with the window  */
  707.         /* in this case I don't care if the alias needed to be updated or not, this ain't */
  708.         /* a real time critical routine */
  709.         myErr = ResolveAlias(nil, ((*theWind)->fileAliasHandle), &saveFileSpec, &myWasChanged);
  710.         if (myErr) {
  711.             ShowMe("\pResolving Alias ", myErr, __LINE__);
  712.             return;
  713.         }
  714.         /* kill current file, ignoring errors */
  715.         FSpDelete(&saveFileSpec);
  716.     }
  717.     SpinCursor();
  718.     /* I'm saving this as MPW TEXT */
  719.     myErr = FSpCreate(&saveFileSpec, kMPWSignature, 'TEXT', 1);
  720.     if (myErr) {
  721.         ShowMe("\pCreating AES file, Do you have it open in MPW? ", myErr, __LINE__);
  722.         InitCursor();
  723.         return;
  724.     }
  725.     
  726.     /* replace the nil handle with the alias record please, in our window data struct */
  727.     DisposeHandle((Handle)(*theWind)->fileAliasHandle);
  728.     if (myErr = NewAlias(nil, &saveFileSpec, &((*theWind)->fileAliasHandle))) {
  729.         ShowMe("\pDuring New Alias ", myErr, __LINE__);
  730.         InitCursor();
  731.         return;
  732.     }
  733.     myErr = FSpOpenDF(&saveFileSpec, fsRdWrPerm, &fileRef);
  734.     if (myErr) {
  735.         ShowMe("\pOpening AES file  Do you have it open in MPW?", myErr, __LINE__);
  736.         SetMyCursor(actsToIDs[(*theWind)->currentAction]);
  737.         return;
  738.     }
  739.     theText = (Handle)TEGetText((*theWind)->boxHandle);
  740.     textSize = GetHandleSize(theText);
  741.     HLock(theText);
  742. /* going to write 80 chars, carrage return, 80 chars, etc. */
  743.     do{
  744.     if(textSize > 80)
  745.         toWrite = 80;
  746.     else 
  747.         toWrite = textSize;
  748.         
  749.     myErr = FSWrite(fileRef, &toWrite, (Ptr)(*theText + currentOffset));
  750.     if(myErr){
  751.             ShowMe("\pWriting to AES file ", myErr, __LINE__);
  752.             break;
  753.     }
  754.     if(textSize < 80){
  755.     break;
  756.     } else {
  757.     SpinCursor();
  758.     FSWrite(fileRef, &oneByte, (Ptr)&carrageRet);
  759.     textSize -= 80;
  760.     currentOffset +=80;
  761.     }
  762.     }while(true);
  763.     HUnlock(theText);
  764.     FSClose(fileRef);
  765. /* make sure it gets updated now. */
  766. FlushVol("", saveFileSpec.vRefNum);    
  767. InitCursor();
  768.  
  769. }
  770.  
  771. OSErr KillOldPrefs(void)
  772. {
  773.     Handle prefsNameStr;
  774.     FSSpec prefsSpec;
  775.     short foundVREF;
  776.     OSErr error;
  777.     long foundDIR;
  778.     FindFolder(kOnSystemDisk, kPreferencesFolderType, true, &foundVREF, &foundDIR);
  779.     prefsNameStr = GetResource('STR ', kPrefsFileString);
  780.     HLock(prefsNameStr); 
  781.     FSMakeFSSpec(foundVREF, foundDIR, (Str255)*prefsNameStr, &prefsSpec);
  782.     error = FSpDelete(&prefsSpec);
  783.     HUnlock(prefsNameStr);
  784.     ReleaseResource(prefsNameStr);
  785. return(error);
  786.  
  787. }
  788. #undef __FILES__
  789.